import PySide6
from PySide6 import QtCore
from PySide6.QtCore import Qt, QSize, Signal, QEvent, QObject
from PySide6.QtGui import QDoubleValidator
from PySide6.QtWidgets import QDialog, QGridLayout, QPushButton, QVBoxLayout, QHBoxLayout, QLabel, QLineEdit, \
    QMessageBox, QComboBox, QAbstractItemView, QTableWidget, QTableWidgetItem, QSizePolicy, QProgressBar, QFrame

from extend_ui.err_log import log_decorator


class Dialog_Process(QDialog):
    signal_update = Signal(int)

    def __init__(self, parent=None, title='进度条', max=100):
        super(Dialog_Process, self).__init__(parent)
        # 获取变量
        self.title = title
        self.max = max
        # 声明变量

        # 关联信号
        self.signal_update.connect(self.update_progress)
        # 初始化控件
        self.initLayout()

    def initLayout(self):
        """ 初始化控件 """
        # 设置无边框dialog
        self.setWindowFlags(Qt.Dialog | Qt.FramelessWindowHint)
        # 设置主题为 QFrame
        self.frame = QFrame(self)
        self.frame.setFixedSize(QSize(300, 100))
        self.frame.setFrameShape(QFrame.Box)
        self.frame.setLineWidth(4)
        self.frame.setFrameShadow(QFrame.Raised)
        self.layout = QVBoxLayout()
        self.frame.setLayout(self.layout)
        # 添加一个文字提示
        self.label = QLabel(self.title)
        self.layout.addWidget(self.label)
        # 添加一个进度条
        self.progress = QProgressBar()
        self.layout.addWidget(self.progress)
        self.progress.setRange(0, self.max)
        self.open()

    def update_progress(self, num):
        self.progress.setValue(self.progress.value() + num)
        if self.progress.value() == self.max:
            self.close()

    """ 屏蔽关闭功能 """
    def accept(self) -> None:
        pass

    def reject(self) -> None:
        pass


class Dialog_Base(QDialog):
    def __init__(self, parent=None):
        super(Dialog_Base, self).__init__(parent)
        # 获取变量
        self.signal_table_info = parent.signal_table_info
        self.table_info = parent.table_info
        self.queue_logging = parent.queue_logging
        # 声明变量
        self.var_addr = 0

        # 初始化
        # self.setWindowTitle('查看具体数据')
        self.layout = QVBoxLayout(self)
        self.add_widget()
        self.initLayout()

        # 生成定制器
        self.timer_refresh = QtCore.QTimer()
        self.timer_refresh.timeout.connect(self.refresh)
        self.timer_refresh.start(500)

    def add_widget(self):
        """ 添加区别控件 """
        pass

    def initLayout(self):
        """ 声明共同的控件 """
        self.setWindowTitle('查看具体数据')
        self.button_ok = QPushButton('OK')
        self.button_ok.clicked.connect(self.button_ok_slot)
        self.button_cancel = QPushButton('Cancel')
        self.button_cancel.clicked.connect(self.button_cancel_slot)
        button_layout = QHBoxLayout()
        button_layout.addWidget(self.button_ok)
        button_layout.addWidget(self.button_cancel)
        self.layout.addLayout(button_layout)

    def display(self, para_addr):
        """ 显示 """
        self.exec_()

    def refresh(self):
        """ 如果只读的话 刷新当前值 """
        pass

    def button_ok_slot(self):
        """ ok 按钮的响应 """
        self.close()

    def button_cancel_slot(self):
        """ 取消的按钮响应 """
        self.close()

    def closeEvent(self, arg__1: PySide6.QtGui.QCloseEvent) -> None:
        self.deleteLater()


class My_Label(QLabel):
    doubleclicked = Signal()

    def mouseDoubleClickEvent(self, event:PySide6.QtGui.QMouseEvent) -> None:
        self.doubleclicked.emit()
        super().mouseDoubleClickEvent(event)


class My_LineEdit(QLineEdit):
    doubleclicked = Signal()

    def mouseDoubleClickEvent(self, event:PySide6.QtGui.QMouseEvent) -> None:
        self.doubleclicked.emit()
        super().mouseDoubleClickEvent(event)


class Dialog_Edit(Dialog_Base):
    def __init__(self, parent=None):
        super(Dialog_Edit, self).__init__(parent)
        self.open_default = 0           # 用于保存打开时的记录

    def add_widget(self):
        self.label = QLabel()
        self.label.setAlignment(Qt.AlignCenter)
        self.edit = QLineEdit()
        self.edit.setAlignment(Qt.AlignCenter)
        doubleValidator = QDoubleValidator(self)
        doubleValidator.setNotation(QDoubleValidator.StandardNotation)
        doubleValidator.setDecimals(8)
        self.edit.setValidator(doubleValidator)
        self.layout.addWidget(self.label)
        self.layout.addWidget(self.edit)

        # 设置默认值的功能框架
        self.label2 = QLabel()
        self.label2.setText('缺省值:')
        self.label2.setAlignment(Qt.AlignVCenter)

        self.edit2 = My_LineEdit()
        self.edit2.setEnabled(False)
        self.edit2.hide()
        self.edit2.setAlignment(Qt.AlignCenter)
        self.edit2.setValidator(doubleValidator)
        self.edit2.doubleclicked.connect(self.set_lineEdit_Enable)

        self.label3 = My_Label()
        self.label3.setAlignment(Qt.AlignCenter)
        self.label3.doubleclicked.connect(self.set_lineEdit_Enable)
        self.label3.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)

        self.layout_default = QHBoxLayout()
        self.layout_default.addWidget(self.label2)
        self.layout_default.addWidget(self.label3)
        self.layout_default.addWidget(self.edit2)
        self.layout.addLayout(self.layout_default)

    def set_lineEdit_Enable(self):
        if self.edit2.isEnabled():
            self.edit2.hide()
            self.label3.show()
            self.edit2.setText(str(self.open_default))
            self.edit2.setEnabled(False)
        else:
            self.edit2.setEnabled(True)
            self.label3.hide()
            self.edit2.show()
            self.edit2.setFocus()
            self.edit2.selectAll()

    @log_decorator
    def display(self, para_addr):
        self.var_addr = para_addr
        min = self.table_info['var_min'][self.var_addr]
        if min == '' or min is None:
            min_text = '-∞'
            self.min = -9999999999
        else:
            min_text = str(min)
            self.min = float(min)
        max = self.table_info['var_max'][self.var_addr]
        if max == '' or max is None:
            max_text = '+∞'
            self.max = 9999999999
        else:
            max_text = str(max)
            self.max = float(max)
        unit = self.table_info['var_unit'][self.var_addr]
        if self.table_info['var_current'][self.var_addr] in ['', 0]:
            old_num = float(0.0)
        else:
            old_num = self.table_info['var_current'][self.var_addr]
        self.label.setText(self.table_info['type_lv2'][self.var_addr] + '-' +
                           self.table_info['var_comment'][self.var_addr] + '\n标准范围：(' +
                           min_text + '--' + max_text + ')')
        self.edit.setText(str(old_num))
        self.edit.setFocus()
        if self.table_info['isWritable'][self.var_addr] == 1:
            self.edit.setReadOnly(False)
        else:
            self.edit.setReadOnly(True)

        # 刷新记录默认值
        self.open_default = self.table_info['var_default'][self.var_addr]
        if self.open_default is None or self.open_default == '':
            if self.table_info['var_type'][self.var_addr] in ['5', 'bit', '3', 'enum', '1', 'int']:
                self.open_default = 0
            else:
                self.open_default = 0.0
        self.label3.setText(str(self.open_default))
        self.edit2.setText(str(self.open_default))

        super().display(para_addr)

    def refresh(self):
        if self.table_info['isWritable'][self.var_addr] == 1:
            pass
        else:
            if self.table_info['var_type'][self.var_addr] in ['5', 'bit']:
                self.edit.setText(str(hex(self.table_info['var_current'][self.var_addr])))
            else:
                self.edit.setText(str(self.table_info['var_current'][self.var_addr]))

    def button_ok_slot(self):
        # 输入值判断
        if float(self.edit.text()) > self.max:
            QMessageBox.critical(self, '提示', '输入超出最大值\n请重新输入', QMessageBox.Yes)
        elif float(self.edit.text()) < self.min:
            QMessageBox.critical(self, '提示', '输入低于最小值\n请重新输入', QMessageBox.Yes)
        # 默认值判断
        elif float(self.edit2.text()) > self.max:
            QMessageBox.critical(self, '提示', '缺省值输入超出最大值\n请重新输入', QMessageBox.Yes)
        elif float(self.edit2.text()) < self.min:
            QMessageBox.critical(self, '提示', '缺省值输入低于最小值\n请重新输入', QMessageBox.Yes)
        else:
            if self.table_info['var_type'][self.var_addr] in ['5', 'bit', '3', 'enum', '1', 'int']:
                self.signal_table_info.emit(1, [self.var_addr], [int(float(self.edit.text()))])
            else:
                self.signal_table_info.emit(1, [self.var_addr], [float(self.edit.text())])
            if float(self.edit2.text()) != self.open_default:
                if self.table_info['var_type'][self.var_addr] in ['5', 'bit', '3', 'enum', '1', 'int']:
                    self.signal_table_info.emit(6, [self.var_addr], [int(float(self.edit2.text()))])
                else:
                    self.signal_table_info.emit(6, [self.var_addr], [float(self.edit2.text())])
            super().button_ok_slot()


class Dialog_Combox(Dialog_Base):
    def __init__(self, parent=None):
        super(Dialog_Combox, self).__init__(parent)

    def add_widget(self):
        self.label = QLabel()
        self.label.setAlignment(Qt.AlignCenter)
        self.combox = QComboBox()
        self.layout.addWidget(self.label)
        self.layout.addWidget(self.combox)

    @log_decorator
    def display(self, para_addr):
        self.var_addr = para_addr
        self.label.setText(
            self.table_info['type_lv2'][self.var_addr] + '-' + self.table_info['var_comment'][self.var_addr])
        self.combox.clear()
        self.combox.addItems(list(self.table_info['action_define'][self.var_addr].values()))
        self.combox.setCurrentIndex(list(self.table_info['action_define'][self.var_addr].keys()).index(
            str(int(self.table_info['var_current'][self.var_addr]))))
        if self.table_info['isWritable'][self.var_addr] == 1:
            self.combox.setEnabled(True)
        else:
            self.combox.setEnabled(False)
        super().display(para_addr)

    def button_ok_slot(self):
        self.signal_table_info.emit(1, [self.var_addr], [
            int(list(self.table_info['action_define'][self.var_addr].keys())[self.combox.currentIndex()])])
        super().button_ok_slot()


class Dialog_Table(Dialog_Base):
    def __init__(self, parent=None):
        super(Dialog_Table, self).__init__(parent)
        self.setMaximumHeight(900)

    def add_widget(self):
        self.table = QTableWidget()
        self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.table.setRowCount(10)  # 设置行数
        self.table.setColumnCount(4)  # 设置列数
        self.table.verticalHeader().setVisible(False)  # 设置表头状态
        self.table.setHorizontalHeaderLabels(['参数地址', '参数名称', '当前值（单位）', '类型'])  # 设置列名
        self.table.setEditTriggers(QAbstractItemView.NoEditTriggers)  # 禁止编辑
        self.table.setSelectionBehavior(QAbstractItemView.SelectRows)  # 设置选择行为为单行
        self.layout.addWidget(self.table)

    @log_decorator
    def display(self, para_addr):
        self.var_addr = para_addr
        real_addr = []
        para_name = []  # 参数名
        curr_value = []  # 当前值
        RW_type = []  # 读写类型
        for i in range(len(self.table_info['action_define'][self.var_addr])):
            real_addr.append(str(self.var_addr))
            para_name.append(str(list(self.table_info['action_define'][self.var_addr].values())[i]))
            curr_value.append(str((int(self.table_info['var_current'][self.var_addr]) >> int(
                list(self.table_info['action_define'][self.var_addr].keys())[i])) & 1))
            RW_type.append('Ro')
        self.table.setRowCount(len(real_addr))  # 设置行数
        for i in range(len(real_addr)):
            tableitem1 = QTableWidgetItem(real_addr[i])
            tableitem1.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
            tableitem2 = QTableWidgetItem(para_name[i])
            tableitem2.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
            tableitem3 = QTableWidgetItem(curr_value[i])
            tableitem3.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
            tableitem4 = QTableWidgetItem(RW_type[i])
            tableitem4.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
            self.table.setItem(i, 0, tableitem1)
            self.table.setItem(i, 1, tableitem2)
            self.table.setItem(i, 2, tableitem3)
            self.table.setItem(i, 3, tableitem4)
        self.resize(QSize(425, 80 + len(real_addr) * 30))
        super().display(para_addr)

    def refresh(self):
        if self.var_addr != 0:
            for j in range(self.table.rowCount()):
                self.table.item(j, 2).setText(
                    str((int(self.table_info['var_current'][self.var_addr]) >> int(
                        list(self.table_info['action_define'][self.var_addr].keys())[j])) & 1))
